﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RayDen.Library.Core;
using RayDen.Library.Core.Primitives;
using RayDen.RayEngine.Core.Types;
using RayDen.RayEngine.Data;

namespace RayDen.RayEngine.VertexFramework
{

    public interface IPathSamplingTechnique
    {
        bool Match(ref SurfaceIntersectionData hit);
        bool NextVertex(ref SurfaceIntersectionData hit, ref RayData pathRay, ref RgbSpectrum throughput, int depth,out float pdf);
    }

    public class PathSamplingTechniqueBase
    {
        public RayEngineScene Scene;
    }

    public class ImplicitLightPathSamplingTechnique : PathSamplingTechniqueBase, IPathSamplingTechnique
    {
        public bool Match(ref SurfaceIntersectionData hit)
        {
            return hit.IsLight;
        }

        public bool NextVertex(ref SurfaceIntersectionData hit, ref RayData pathRay, ref RgbSpectrum throughput, int depth, out float pdf)
        {
            var currentTriangleIndex = (int)hit.Hit.Index;
            var lt = Scene.GetLightByIndex(currentTriangleIndex);
            var wo = -pathRay.Dir;
            pdf = 1f;
            if (hit.Brdf.IsSpecular() || depth == 1)
            {
                if (lt != null)
                {
                    var le = hit.Color * lt.Emittance(ref wo, out pdf);
                    throughput.MAdd(ref throughput, ref le);
                }
            }

            return false;
        }
    }

    public class ExplicitLightPathSamplingTechnique : PathSamplingTechniqueBase, IPathSamplingTechnique
    {
        public bool Match(ref SurfaceIntersectionData hit)
        {
            return hit.Brdf.IsDiffuse();
        }

        public bool NextVertex(ref SurfaceIntersectionData hit, ref RayData pathRay, ref RgbSpectrum throughput, int depth, out float pdf)
        {
            var currentTriangleIndex = (int)hit.Hit.Index;
            var lt = Scene.GetLightByIndex(currentTriangleIndex);
            var wo = -pathRay.Dir;
            pdf = 1f;
            if (hit.Brdf.IsSpecular() || depth == 1)
            {
                if (lt != null)
                {
                    var le = hit.Color * lt.Emittance(ref wo, out pdf);
                    throughput.MAdd(ref throughput, ref le);
                }
            }

            return false;
        }
    }

}
